// src/composables/useAuth.ts
import { ref } from 'vue';
import axiosInstance, { setAuthHeader } from '@/axios/axios';
import { ElMessage } from 'element-plus';
import { post, get } from '@/axios/api'; // 你现有的封装
import { isArrayLike } from 'lodash';


const token: any = ref<string | null>(localStorage.getItem('access_token') || null);
const refresh: any = ref(localStorage.getItem('refresh_token'));

const user = ref<any>(null);

const CLIENT_SIDE_HASH = 'true';

if (token.value) setAuthHeader(token.value);

export async function sha256Hex(message: string): Promise<string> {
    // 1. 强判是否为 Node（优先）
    const isNode = typeof process !== 'undefined' && !!(process.versions && process.versions.node);

    if (isNode) {
        try {
            // 使用动态 import，避免打包工具在前端将 crypto 引入 bundle
            const cryptoNode = await import('crypto');
            if (cryptoNode && typeof cryptoNode.createHash === 'function') {
                return cryptoNode.createHash('sha256').update(message, 'utf8').digest('hex');
            }
        } catch (e:any) {
            // 打印日志以便排查（部署环境可以查看）
            // eslint-disable-next-line no-console
            console.warn("import('crypto') failed:", e && e.message ? e.message : e);
            // 继续尝试其他路径
        }
    }

    // 2. Web Crypto（浏览器/worker/Deno）
    try {
        const maybeCrypto = (globalThis as any).crypto || (globalThis as any).msCrypto;
        if (maybeCrypto?.subtle && typeof maybeCrypto.subtle.digest === 'function') {
            if (typeof TextEncoder === 'undefined') {
                throw new Error('TextEncoder is not available');
            }
            const enc = new TextEncoder();
            const buf = enc.encode(message);
            const hb = await maybeCrypto.subtle.digest('SHA-256', buf);
            const bytes = new Uint8Array(hb);
            return Array.from(bytes)
                .map(b => b.toString(16).padStart(2, '0'))
                .join('');
        }
    } catch (e:any) {
        // eslint-disable-next-line no-console
        console.warn('WebCrypto path failed:', e && e.message ? e.message : e);
    }

    // 3. 最后回退：纯 JS 实现（js-sha256）
    try {
        // lazy import 回退库，避免在无网络/特殊环境下失败
        const mod = await import('js-sha256');
        const sha256 = (mod && (mod.sha256 || (mod as any).default?.sha256)) || mod.default || mod;
        if (typeof sha256 === 'function') {
            // js-sha256 返回小写 hex
            return sha256(message);
        }
    } catch (e:any) {
        // eslint-disable-next-line no-console
        console.warn('js-sha256 import failed:', e && e.message ? e.message : e);
    }

    // 4. 无可用实现
    throw new Error('No SHA-256 implementation available in this environment.');
}

/**
 * login: 更健壮的登录方法
 * - username, password: 明文（函数内部可选做 sha256）
 * - 返回：{ user, tokens } 或抛出 Error（错误信息在 Error.message）
 */
export async function login(username: string, password: string) {
    if (!username || !password) {
        ElMessage.error('请填写用户名和密码');
        return {
            success: false,
            message: '请填写用户名和密码'
        }
    }

    try {
        // 若启用客户端哈希，则把 password 替换成 sha256 hex
        const payloadPassword = CLIENT_SIDE_HASH ? await sha256Hex(password) : password;

        // 注意：如果后端并未做对应改动，启用 CLIENT_SIDE_HASH 会导致认证失败。
        // 同时我们向后端仍然使用字段名 `password`，如果你后端要求另一个字段名（例如 hashed_password），需调整。
        const resp = await post('/auth/login/', { username, password: payloadPassword });
        const data:any = resp.data ?? resp;

        if (!data || !data.access) {
            // 处理后端返回但无 token 的情况
            const serverMsg = data?.detail ?? JSON.stringify(data) ?? '登录失败（没有返回 access token）';
            return {
                success: false,
                message: serverMsg
            };
        }

        // 保存 token 并设置 header（**必须在请求 /auth/me 之前**）
        token.value = data.access;
        refresh.value = data.refresh ?? null;
        localStorage.setItem('access_token', token.value);
        if (refresh.value) localStorage.setItem('refresh_token', refresh.value);
        setAuthHeader(token.value);

        // 现在加载用户 profile（auth/me），确保请求包含 Authorization 头
        try {
            const meResp = await get('/auth/me/');
            if (meResp && meResp.data) {
                user.value = meResp.data;
            }
            return {
                user: user.value,
                tokens: { access: token.value, refresh: refresh.value },
                success: true
            };
        } catch (e: any) {
            // 如果获取 profile 失败（例如 401），清理 token 并向上抛出
            console.error('loadUser failed after login:', e?.response?.data ?? e.message ?? e);
            // 清理
            token.value = null;
            refresh.value = null;
            localStorage.removeItem('access_token');
            localStorage.removeItem('refresh_token');
            setAuthHeader(null);
            return {
                success: false,
                message: e
            };
        }
    } catch (err: any) {
        // 统一错误处理：区分网络错误与认证错误
        console.log(err)
        let msg = '登录失败';
        if (err?.response) {
            // axios 错误对象
            const status = err.response.status;
            const d = err.response.data;
            if (status === 400 || status === 401) {
                msg =
                    d && (d.detail || d.non_field_errors || d.message)
                        ? d.detail || d.non_field_errors || d.message
                        : '用户名或密码错误';
            } else {
                msg = d?.detail ?? d?.message ?? `服务器返回 ${status}`;
            }
        } else if (err instanceof Error) {
            msg = err.message;
        }
        // 给用户提示（调用处也可以自己处理）
        ElMessage.error(msg[0]);
        // 向调用者抛出 Error（含 message），以保持原语义
        return {
            message: msg,
            success: false,
        }
    }
}
export async function register(payload: any) {
    // payload may include avatar via multipart - handle separately
    await axiosInstance.post('auth/register/', payload);
}

export async function loadUser() {
    try {
        const res = await axiosInstance.get('auth/me/');
        user.value = res.data;
        // if (res && res.data) {
        //     ElMessage.success("Logged in successfully")
        // }
        return res.data;
    } catch (err: any) {
        const resp = err?.response;
        // 常见 SimpleJWT 返回：status 401 + code token_not_valid
        if (resp && resp.status === 401 && resp.data?.code === 'token_not_valid') {
            const refreshToken = localStorage.getItem('refresh_token');

            if (!refreshToken) {
                // 没有 refresh token，直接清理并跳转登录
                clearAuthAndRedirect('Session expired — please log in again.');
                return;
            }

            // 尝试用 refresh token 刷新 access token
            try {
                const refreshResp = await axiosInstance.post(REFRESH_URL, {
                    refresh: refreshToken
                });

                // 兼容不同后端字段名：access / token / access_token
                const newAccess =
                    refreshResp?.data?.access ?? refreshResp?.data?.token ?? refreshResp?.data?.access_token ?? null;

                if (!newAccess) {
                    // 刷新接口成功返回但没有 access 字段 —— 视为失败
                    throw new Error('No access token in refresh response');
                }

                // 保存新 access token 并更新 axios header
                localStorage.setItem('access_token', newAccess);
                axiosInstance.defaults.headers.common['Authorization'] = `Bearer ${newAccess}`;

                // 用新 token 重试一次获取用户信息
                const retry = await axiosInstance.get('auth/me/');
                user.value = retry.data;

                ElMessage({
                    message: 'Session refreshed',
                    type: 'success',
                    showClose: true
                });

                return retry.data;
            } catch (refreshErr) {
                // 刷新失败 —— 清理凭证并跳转登录
                console.error('Token refresh failed:', refreshErr);
                clearAuthAndRedirect('Session expired — please log in again.');
                return;
            }
        }

        // 其它错误类型
        console.error('loadUser failed:', err);
        // ElMessage.error('Failed to load user info.');
        return;
    }
}
export function logout() {
    token.value = null;
    user.value = null;
    localStorage.removeItem('access_token');
    setAuthHeader(null);
    ElMessage({
        message: '登出成功',
        type: 'success'
    });
    setTimeout(() => {
        window.location.href = '/hospital/';
    }, 1000);
}

const REFRESH_URL = 'auth/token/refresh/';
function clearAuthAndRedirect(message = 'Please log in again') {
    try {
        localStorage.removeItem('access_token');
        localStorage.removeItem('refresh_token');
    } catch (e) {
        // ignore
    }
    if (axiosInstance && axiosInstance.defaults && axiosInstance.defaults.headers) {
        delete axiosInstance.defaults.headers.common['Authorization'];
    }

    ElMessage({
        message,
        type: 'warning',
        showClose: true
    });

    // 跳转到登录页：这里用 window.location，避免依赖 router 实例
    window.location.href = '/hospital/login';
}

export function useAuth() {
    return { token, user, login, logout, register, loadUser };
}

export { token, user };
